package ast2

import (
	"fmt"
	"strconv"
	"strings"
	"sync"

	"gitee.com/u-language/u-language/ucom/astdata"
	"gitee.com/u-language/u-language/ucom/data"
	"gitee.com/u-language/u-language/ucom/enum"
	"gitee.com/u-language/u-language/ucom/errcode"
	"gitee.com/u-language/u-language/ucom/internal/errutil"
	"gitee.com/u-language/u-language/ucom/internal/utils"
)

// 节点接口，代表一个抽象语法树节点
type Node interface {
	String() string
	C(buf *strings.Builder)
}

// 表达式接口，代表一个表达式
type Expr interface {
	Node
	expr()
}

type node struct {
	LineNum int
}

var (
	varname   = "变量名"
	constname = "常量名"
)

var _ Node = (*VarNode)(nil)
var _ Node = (*FuncNode)(nil)
var _ Node = (*ASSIGNNode)(nil)
var _ Node = (*Object)(nil)
var _ Expr = (*OpExpr)(nil)
var _ Node = (*RbraceNode)(nil)
var _ Node = (*IfNode)(nil)
var _ Node = (*ElseNode)(nil)
var _ Node = (*ForNode)(nil)
var _ Node = (*CallNode)(nil)
var _ Node = (*ReturnNode)(nil)
var _ Node = (*GotoStmt)(nil)
var _ Node = (*LabelNode)(nil)
var _ Node = (*BreakStmt)(nil)
var _ Node = (*ContinueStmt)(nil)
var _ Node = (*ConstNode)(nil)
var _ Node = (*StructDecl)(nil)
var _ Node = (*Objects)(nil)
var _ Node = (*SelfOpStmt)(nil)
var _ Node = (*SwitchNode)(nil)
var _ Node = (*CaseNode)(nil)
var _ Node = (*DefaultNode)(nil)
var _ Node = (*MethodNode)(nil)
var _ Node = (*AutoFreeNode)(nil)
var _ Node = (*EnumDecl)(nil)
var _ Node = (*IndexExpr)(nil)
var _ Node = (*GenericInstantiation)(nil)
var _ Node = (*DerefExpr)(nil)

var _ astdata.Typ = (*Object)(nil)
var _ astdata.Typ = (*Objects)(nil)
var _ astdata.Typ = (*StructDecl)(nil)
var _ astdata.Typ = (*Array)(nil)
var _ astdata.Typ = (*GenericInstantiation)(nil)
var _ astdata.Typ = (*EnumDecl)(nil)

var _ Expr = (*Object)(nil)
var _ Expr = (*Objects)(nil)
var _ Expr = (*CallNode)(nil)
var _ Expr = (*OpExpr)(nil)
var _ Expr = (*IndexExpr)(nil)
var _ Expr = (*DerefExpr)(nil)

var _ set_nosemicolon_interface = (*VarNode)(nil)
var _ set_nosemicolon_interface = (*ASSIGNNode)(nil)
var _ set_nosemicolon_interface = (*OpExpr)(nil)
var _ set_nosemicolon_interface = (*SelfOpStmt)(nil)
var _ set_nosemicolon_interface = (*CallNode)(nil)

type CType interface {
	CType(buf *strings.Builder)
}

var _ CType = (*Object)(nil)
var _ CType = (*Objects)(nil)

type set_nosemicolon_interface interface {
	SetNosemicolon(nosemicolon bool)
}

var _ CDecl = (*VarNode)(nil)
var _ CDecl = (*ConstNode)(nil)
var _ CDecl = (*StructDecl)(nil)
var _ CDecl = (*EnumDecl)(nil)
var _ CDecl = (*FuncNode)(nil)
var _ CDecl = (*MethodNode)(nil)

// CDecl 表示一个支持生成C头文件的一个声明语句的类型
type CDecl interface {
	Node
	CDecl(buf *strings.Builder)
}

// 变量声明节点
type VarNode struct {
	TYPE        astdata.Typ //变量类型
	Value       Expr        //值
	Name        string      //变量名
	Tmp         *VarNode    //处理变量遮蔽
	CType       string
	InFunc      bool
	nosemicolon bool
	node
}

// NewVarNode 创建变量声明节点
func NewVarNode(name string, InFunc bool, LineNum int) *VarNode {
	ret := &VarNode{Name: name, InFunc: InFunc}
	ret.LineNum = LineNum
	return ret
}

func (n *VarNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, n) {
		return buf.String()
	}
	buf.WriteString("*ast2.VarNode")
	buf.WriteString(fmt.Sprintf("%+v", *n))
	return buf.String()
}

func (v *VarNode) C(buf *strings.Builder) {
	if v.CType == "" {
		tocVarNode(v)
	}
	if v.Tmp != nil {
		v.Tmp.C(buf)
	}
	buf.Grow(65)
	buf.WriteString(v.CType)
	buf.WriteString(" ")
	buf.WriteString(v.Name)
	if v.InFunc && v.Value != nil { //是局部变量初始化
		buf.WriteString(" = ")
		v.Value.C(buf)
	}
	if !v.nosemicolon {
		buf.WriteString(" ;")
	}
}

func (n *VarNode) SetNosemicolon(nosemicolon bool) {
	n.nosemicolon = nosemicolon
}

func (v *VarNode) CDecl(buf *strings.Builder) {
	tocVarNode(v)
	buf.Grow(65)
	buf.WriteString("extern ")
	buf.WriteString(v.CType)
	buf.WriteString(" ")
	buf.WriteString(v.Name)
	buf.WriteString(" ;")
}

func tocVarNode(n *VarNode) {
	typ := n.TYPE.Typ()
	if typ[0] == '[' { //如果是连续类型
		elem, Len := new(strings.Builder), new(strings.Builder)
		splitElemAndLen(elem, Len, typ)
		n.Name, n.CType = n.Name+Len.String(), typeToC(elem.String())
	} else {
		n.CType = typeToC(typ)
	}
}

// splitElemAndLen 分割元素类型与长度
// 对于单维数组 [expr]x elem写入 x Len 写入 [expr]
// 对于多维数组 [expr]x elem写入 x Len 写入 所有的[expr]
func splitElemAndLen(elem, Len *strings.Builder, typ string) {
	if typ[0] == '[' {
		e, l, _ := utils.Elem(typ)
		Len.WriteString(l)
		splitElemAndLen(elem, Len, e)
		return
	}
	elem.WriteString(typ)
}

// FuncInfo 函数信息
type FuncInfo struct {
	Name       string
	Parame     []astdata.Parame
	RetValue   []astdata.RetValue
	TypeParame []astdata.NameAndType
	codeBlock
}

func (f *FuncInfo) String() string {
	return fmt.Sprintf("%+v", *f)
}

// 函数节点
type FuncNode struct {
	*FuncInfo
}

// NewFuncNode 创建函数节点
func NewFuncNode(info *FuncInfo) *FuncNode {
	var ret FuncNode
	ret.FuncInfo = info
	return &ret
}

func (f *FuncNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, f) {
		return buf.String()
	}
	buf.WriteString("*ast2.FuncNode{\n")
	buf.WriteString(fmt.Sprintf("name=%s\t", f.Name))
	buf.WriteString(fmt.Sprintf("Parame=%s\t", f.Parame))
	buf.WriteString(fmt.Sprintf("RetValue=%s\t", f.RetValue))
	buf.WriteString(fmt.Sprintf("TypeParame=%s\n", f.TypeParame))
	buf.WriteString(f.Sbt.String())
	return buf.String()
}

func (f *FuncNode) C(buf *strings.Builder) {
	buf.Grow(100)
	if f.Name == "main" {
		buf.WriteString("int main(){\n")
		buf.WriteString("main__init();\n")
	} else {
		if len(f.RetValue) != 0 {
			buf.WriteString(typeToC(f.RetValue[0].Type.Typ()))
		} else {
			buf.WriteString("void")
		}
		buf.WriteString(" ")
		buf.WriteString(f.Name)
		buf.WriteString("(")
		plen := len(f.Parame)
		for i := 0; i < plen; i++ {
			buf.WriteString(typeToC(f.Parame[i].Type.Typ()))
			buf.WriteString(" ")
			buf.WriteString(f.Parame[i].Name)
			if i+1 < plen {
				buf.WriteString(",")
			}
		}
		buf.WriteString("){")
	}
}

func (f *FuncNode) CDecl(buf *strings.Builder) {
	if f.TypeParame != nil {
		return
	}
	buf.Grow(100)
	if f.Name == "main" {
		buf.WriteString("int main();\n")
		return
	}
	if len(f.RetValue) != 0 {
		buf.WriteString(typeToC(f.RetValue[0].Type.Typ()))
	} else {
		buf.WriteString("void")
	}
	buf.WriteString(" ")
	buf.WriteString(f.Name)
	buf.WriteString("(")
	plen := len(f.Parame)
	for i := 0; i < plen; i++ {
		buf.WriteString(typeToC(f.Parame[i].Type.Typ()))
		buf.WriteString(" ")
		buf.WriteString(f.Parame[i].Name)
		if i+1 < plen {
			buf.WriteString(",")
		}
	}
	buf.WriteString(");")
}

// 赋值节点
type AssignmentNode struct {
	//目的操作数，源操作数
	Dest        Expr
	Src         Expr
	nosemicolon bool
	node
}

type ASSIGNNode = AssignmentNode

// NewASSIGNNode 创建赋值节点
func NewASSIGNNode(Dest Expr, Src Expr, LineNum int) *ASSIGNNode {
	ret := &ASSIGNNode{
		Dest: Dest,
		Src:  Src,
	}
	ret.LineNum = LineNum
	return ret
}

func (a *ASSIGNNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, a) {
		return buf.String()
	}
	buf.WriteString("*ast2.ASSIGNode{")
	buf.WriteString("\nDest:")
	buf.WriteString(a.Dest.String())
	buf.WriteString("\nSrc:")
	buf.WriteString(a.Src.String())
	buf.WriteString("\n\t}")
	return buf.String()
}

func (a *ASSIGNNode) C(buf *strings.Builder) {
	buf.Grow(50)
	a.Dest.C(buf)
	buf.WriteString(" = ")
	a.Src.C(buf)
	if !a.nosemicolon {
		buf.WriteString(" ;")
	}
}

func (a *ASSIGNNode) SetNosemicolon(nosemicolon bool) {
	a.nosemicolon = nosemicolon
}

// 对象类型枚举
type ObjKind int

const (
	NoKind ObjKind = 1 << iota
	INTOBJ
	FLOATOBJ
	BoolObj
	StringObj
	SymbolObj
	LeaObj
	DerefObj
	StructPtr
	NilObj
	EnumObj
	TypeObj
)

var (
	ObjKindSrtMap = [...]string{
		NoKind:    "nokind (未定义的枚举)",
		INTOBJ:    "intobj (整数)",
		FLOATOBJ:  "floatobj (浮点数)",
		BoolObj:   "boolobj (布尔值)",
		StringObj: "stringobj（字符串）",
		SymbolObj: "SymbolObj (符号)",
		LeaObj:    "leaObj (取地址)",
		DerefObj:  "derefObj (解引用)",
		StructPtr: "StructPtr (结构体指针)",
		NilObj:    "NilObj (指针的零值)",
		EnumObj:   "EnumObj (枚举值)",
		TypeObj:   "TypeObj(类型)",
	}
)

func (o ObjKind) String() string {
	var buf strings.Builder
	try_equal(o, INTOBJ, &buf)
	try_equal(o, FLOATOBJ, &buf)
	try_equal(o, BoolObj, &buf)
	try_equal(o, StringObj, &buf)
	try_equal(o, SymbolObj, &buf)
	try_equal(o, LeaObj, &buf)
	try_equal(o, DerefObj, &buf)
	try_equal(o, StructPtr, &buf)
	try_equal(o, NilObj, &buf)
	try_equal(o, EnumObj, &buf)
	try_equal(o, TypeObj, &buf)
	return buf.String()
}

func try_equal(k ObjKind, eq ObjKind, buf *strings.Builder) {
	if k&eq != 0 {
		buf.WriteString(ObjKindSrtMap[eq])
	}
}

// 对象节点
//
// 可能表示
//   - 整数
//   - 浮点数
//   - 布尔值
//   - 符号
//   - 字符串
type Object struct {
	Name string
	Kind ObjKind
}

// 创建对象节点
func NewObject(Kind ObjKind, Name string) *Object {
	ret := &Object{Name: Name}
	ret.Kind = Kind
	return ret
}

func (o *Object) String() string {
	var buf strings.Builder
	if handleNil(&buf, o) {
		return buf.String()
	}
	buf.WriteString("*ast2.Object")
	buf.WriteString(fmt.Sprintf("%+v", *o))
	return buf.String()
}

func (o *Object) Typ() string {
	if o.Kind&LeaObj != 0 {
		if o.Kind&TypeObj != 0 {
			return "&" + o.Name
		}
		return o.Name + "*"
	}
	return o.Name
}

func (o *Object) SetTyp() { o.Kind |= TypeObj }

func (o *Object) Copy() astdata.Typ {
	ret := *o
	return &ret
}

func (o *Object) SetLea(i int) {
	n, leai := utils.Ret_type_no_lea(o.Name)
	if leai == i {
		return
	}
	o.Kind |= LeaObj
	var buf strings.Builder
	buf.Grow(i + len(n))
	buf.WriteString(strings.Repeat("&", i))
	buf.WriteString(n)
	o.Name = buf.String()
}

func (o *Object) C(buf *strings.Builder) {
	buf.Grow(len(o.Name))
	switch o.Kind {
	case INTOBJ, FLOATOBJ, BoolObj, StringObj, SymbolObj, StructPtr, StructPtr | SymbolObj, SymbolObj | EnumObj, TypeObj:
		buf.WriteString(o.Name)
	case LeaObj, LeaObj | StructPtr:
		buf.WriteString("&")
		buf.WriteString(o.Name)
	case DerefObj, DerefObj | StructPtr:
		buf.WriteString("(*")
		buf.WriteString(o.Name)
		buf.WriteString(")")
	case NilObj:
		buf.WriteString("NULL")
	}
}

func (o *Object) CType(buf *strings.Builder) {
	buf.Grow(len(o.Name))
	switch o.Kind {
	case INTOBJ, FLOATOBJ, BoolObj, StringObj, SymbolObj, StructPtr, StructPtr | SymbolObj, SymbolObj | EnumObj, TypeObj:
		buf.WriteString(typeToC(o.Name))
	case LeaObj, LeaObj | StructPtr:
		buf.WriteString(typeToC(o.Name))
		buf.WriteString("*")
	case DerefObj, DerefObj | StructPtr:
		buf.WriteString("(*")
		buf.WriteString(typeToC(o.Name))
		buf.WriteString(")")
	case NilObj:
		buf.WriteString("NULL")
	}
}

func (o *Object) expr() {}

// 运算表达式节点
type OperationExpr struct {
	Src1    Expr
	Src2    Expr
	OP      enum.OPSymbol
	Inparen bool //是否在小括号内
	node
}

// 运算表达式节点
type OpExpr = OperationExpr

// NewOpExpr 创建运算表达式节点
func NewOpExpr(OP enum.OPSymbol, Src1, Src2 Expr, LineNum int) *OpExpr {
	ret := &OpExpr{
		OP:   OP,
		Src1: Src1,
		Src2: Src2,
	}
	ret.LineNum = LineNum
	return ret
}

func (a *OpExpr) String() string {
	var buf strings.Builder
	buf.Grow(10)
	if handleNil(&buf, a) {
		return buf.String()
	}
	buf.WriteString("*ast2.OpExpr{")
	buf.WriteString("\nOP:")
	buf.WriteString(a.OP.String())
	buf.WriteString("\nSrc1:")
	buf.WriteString(a.Src1.String())
	buf.WriteString("\nSrc2:")
	buf.WriteString(a.Src2.String())
	buf.WriteString("\nInparen:")
	buf.WriteString(strconv.FormatBool(a.Inparen))
	buf.WriteString("}")
	return buf.String()
}

func (a *OpExpr) expr() {}

func (a *OpExpr) C(buf *strings.Builder) {
	buf.Grow(10)
	if a.Inparen {
		buf.WriteString("(")
		defer buf.WriteString(")")
	}
	a.Src1.C(buf)
	str, ok := opToStrMap[a.OP]
	if !ok {
		panic(errutil.NewErr2(errutil.CompileErr, fmt.Sprintf("未知的 op: %s", a.OP.String())))
	}
	buf.WriteString(str)
	a.Src2.C(buf)
}

func (o *OpExpr) SetNosemicolon(nosemicolon bool) {
	if s, ok := o.Src1.(set_nosemicolon_interface); ok {
		s.SetNosemicolon(true)
	}
	if s, ok := o.Src2.(set_nosemicolon_interface); ok {
		s.SetNosemicolon(true)
	}
}

var opToStrMap = map[enum.OPSymbol]string{
	enum.ADDOP:      " + ",
	enum.SUBOP:      " - ",
	enum.MULOP:      " * ",
	enum.DIVOP:      " / ",
	enum.LessOP:     " < ",
	enum.GreaterOP:  " > ",
	enum.EqualOP:    " == ",
	enum.NoEqualOP:  " != ",
	enum.RemainOP:   " % ",
	enum.IncOP:      "++",
	enum.DecOP:      "--",
	enum.AndOP:      "&",
	enum.OrOP:       "|",
	enum.XorOp:      "^",
	enum.LogicAndOP: "&&",
	enum.LogicOrOP:  "||",
}

// 右大括号节点
type RbraceNode struct{}

func NewRbraceNode() RbraceNode {
	return RbraceNode{}
}

func (b RbraceNode) String() string {
	var buf strings.Builder
	buf.WriteString("ast2.RbraceNode{}")
	return buf.String()
}

func (b RbraceNode) C(buf *strings.Builder) {
	buf.WriteString("}")
}

// if节点
type IfNode struct {
	codeBlock
	BoolExpr Expr
}

// NewIfNode 创建if节点
func NewIfNode(LineNum int) *IfNode {
	ret := &IfNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (l *IfNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, l) {
		return buf.String()
	}
	buf.WriteString("*ast2.IfNode{\n")
	buf.WriteString(l.BoolExpr.String())
	buf.WriteString(l.Sbt.String())
	buf.WriteString("}")
	return buf.String()
}

func (l *IfNode) C(buf *strings.Builder) {
	buf.Grow(7)
	buf.WriteString("if (")
	l.BoolExpr.C(buf)
	buf.WriteString("){")
}

// else节点
type ElseNode struct {
	codeBlock
	BoolExpr Expr
}

// NewElseNode 创建else节点
func NewElseNode(LineNum int) *ElseNode {
	ret := &ElseNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (l *ElseNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, l) {
		return buf.String()
	}
	buf.WriteString("*ast2.ElseNode{\n")
	if l.BoolExpr != nil {
		buf.WriteString(fmt.Sprintf("boolexpr=%+v\n", l.BoolExpr))
	}
	buf.WriteString(l.Sbt.String())
	buf.WriteString("}")
	return buf.String()
}

func (l *ElseNode) C(buf *strings.Builder) {
	buf.Grow(13)
	buf.WriteString("else ")
	if l.BoolExpr != nil {
		buf.WriteString("if (")
		l.BoolExpr.C(buf)
		buf.WriteString(")")
	}
	buf.WriteString("{\n")
}

// codeBlock 是代码块应该包含的值和方法
type codeBlock struct {
	node
	Sbt *Sbt //当前作用域符号表
}

func newCodeBlock(LineNum int) codeBlock {
	ret := codeBlock{}
	ret.LineNum = LineNum
	ret.Sbt = NewSbt(false)
	return ret
}

func (c *codeBlock) getSbt() *Sbt {
	return c.Sbt
}

// CodeBlockIface 是代码块节点接口
type CodeBlockIface interface {
	Node
	getSbt() *Sbt
}

// for节点
type ForNode struct {
	codeBlock
	InitStmt Node
	BoolExpr Expr
	EndStmt  Node
}

// NewForNode 创建for节点
func NewForNode(LineNum int) *ForNode {
	ret := &ForNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (l *ForNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, l) {
		return buf.String()
	}
	buf.WriteString("*ast2.ForNode{\n")
	if l.InitStmt != nil {
		buf.WriteString("\nInitStmt:")
		buf.WriteString(l.InitStmt.String())
	}
	if l.BoolExpr != nil {
		buf.WriteString("\nBoolStmt:")
		buf.WriteString(l.BoolExpr.String())
	}
	if l.EndStmt != nil {
		buf.WriteString("\nEndStmt:")
		buf.WriteString(l.EndStmt.String())
	}
	buf.WriteString(l.Sbt.String())
	buf.WriteString("}")
	return buf.String()
}

func (l *ForNode) C(buf *strings.Builder) {
	buf.Grow(11)
	buf.WriteString("for (")
	if l.InitStmt != nil {
		l.InitStmt.C(buf)
	} else {
		buf.WriteString(" ;")
	}
	if l.BoolExpr != nil {
		l.BoolExpr.C(buf)
	}
	buf.WriteString(";")
	if l.EndStmt != nil {
		iface := l.EndStmt.(set_nosemicolon_interface)
		iface.SetNosemicolon(true)
		l.EndStmt.C(buf)
	}
	buf.WriteString("){")
}

// 函数调用节点
type CallNode struct {
	FuncName      Expr   //调用函数名
	Parame        []Expr //Parameter
	CCallFuncName string
	nosemicolon   bool
	InAutoFree    bool
	node
}

// NewCallNode 创建函数调用节点
func NewCallExpr(funcname Expr, LineNum int, parame ...Expr) *CallNode {
	ret := new(CallNode)
	ret.FuncName = funcname
	ret.Parame = parame
	ret.LineNum = LineNum
	return ret
}

func (a *CallNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, a) {
		return buf.String()
	}
	buf.WriteString("*ast2.CallNode{")
	buf.WriteString(fmt.Sprintf("%+v}", *a))
	return buf.String()
}

func (c *CallNode) expr() {}

func (c *CallNode) SetNosemicolon(nosemicolon bool) {
	c.nosemicolon = nosemicolon
}

func (a *CallNode) C(buf *strings.Builder) {
	a = utoCCall(a)
	buf.Grow(60)
	defer func() {
		if !a.nosemicolon {
			buf.WriteString(";")
		}
	}()
	pl := len(a.Parame)
	switch a.CCallFuncName {
	case enum.Malloc:
		buf.WriteString("(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString("*)malloc(sizeof(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString("))")
		return
	case enum.Int, enum.Float:
		buf.WriteString("(")
		buf.WriteString(typeToC(a.CCallFuncName))
		buf.WriteString(")")
		a.Parame[0].C(buf)
		return
	case enum.UnsafeAdd:
		buf.WriteString("(((void*)")
		a.Parame[0].C(buf)
		buf.WriteString(")+")
		a.Parame[1].C(buf)
		buf.WriteString(")")
		return
	case enum.UnsafeConvert:
		buf.WriteString("(")
		a.Parame[1].(CType).CType(buf)
		buf.WriteString(")")
		a.Parame[0].C(buf)
		return
	case enum.MallocSize:
		buf.WriteString("malloc(")
		a.Parame[0].C(buf)
		buf.WriteString(")")
		return
	case enum.UnsafeSizeof:
		buf.WriteString("sizeof(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString(")")
		return
	case enum.MemPoolNew:
		buf.WriteString(enum.MemPoolNew)
		buf.WriteString("(")
		a.Parame[0].C(buf)
		buf.WriteString(",")
		if o, ok := a.Parame[1].(*Object); ok && o.Kind == TypeObj { //如果是类型
			buf.WriteString("sizeof(")
			buf.WriteString(typeToC(o.Name))
			buf.WriteString(")")
		} else {
			a.Parame[1].C(buf)
		}
		buf.WriteString(")")
		return
	case enum.UnsafePointer:
		buf.WriteString("(void *)")
		a.Parame[0].C(buf)
		return
	}
	buf.WriteString(a.CCallFuncName)
	buf.WriteString("(")
	for i := 0; i < pl; i++ {
		a.Parame[i].C(buf)
		if i+1 < pl { //如果不是最后一个参数
			buf.WriteString(",")
		}
	}
	buf.WriteString(")")
}

// utoCCall 将调用节点转换为cast等价的
// - c是被转换的，不能为nil
func utoCCall(c *CallNode) *CallNode {
	var funcname string
	var parame []Expr
	poff := 0
	if n, ok := c.FuncName.(*Objects); ok {
		if c.InAutoFree {
			poff = 1
		}
		if n.T != "" { //如果是方法
			poff++
			parame = make([]Expr, len(c.Parame)+1)
			funcname = astdata.Generate_method_symbol(n.T, n.Slice[len(n.Slice)-1].Name)
			receiver := *n
			receiver.Slice = n.Slice[:len(n.Slice)-1]
			parame[poff-1] = &receiver
		} else {
			parame = make([]Expr, len(c.Parame))
			var buf strings.Builder
			buf.WriteString(n.Slice[0].Name)
			for _, v := range n.Slice[1:] {
				buf.WriteString(enum.PackageSep)
				buf.WriteString(v.Name)
			}
			funcname = buf.String()
			if n.IsImportSymbol {
				//TODO:避免不同包同名冲突
				funcname = n.Slice[1].Name
			}
		}
	} else {
		parame = make([]Expr, len(c.Parame))
		//Noto:未来支持a()()，其中a()返回函数类型，这里需要修改
		funcname = c.FuncName.(*Object).Name
	}
	c.CCallFuncName = funcname
	for i := 0; i < len(c.Parame); i++ {
		if parame[i] != nil {
			continue
		}
		parame[i] = c.Parame[i]
	}
	c.Parame = parame
	return c
}

// return节点
type ReturnNode struct {
	RetValue Expr
	LineNum  int
}

func (l *ReturnNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, l) {
		return buf.String()
	}
	buf.WriteString("*ast2.ReturnNode{")
	buf.WriteString(fmt.Sprint(l.RetValue))
	buf.WriteString("}")
	return buf.String()
}

func (l *ReturnNode) C(buf *strings.Builder) {
	buf.Grow(8)
	buf.WriteString("return ")
	if l.RetValue != nil {
		l.RetValue.C(buf)
	}
	buf.WriteString(";")
}

// 缩写： statement 缩写成Stmt

// goto语句
type GotoStmt struct {
	Label string
	node
}

func NewGotoStmt(LineNum int) *GotoStmt {
	ret := &GotoStmt{}
	ret.LineNum = LineNum
	return ret
}

func (g *GotoStmt) String() string {
	return fmt.Sprintf("*ast2.GotoStmt{Label:%s}", g.Label)
}

func (g *GotoStmt) C(buf *strings.Builder) {
	buf.Grow(len(g.Label) + 6)
	buf.WriteString("goto ")
	buf.WriteString(g.Label)
	buf.WriteString(";")
}

// 标签
type LabelNode struct {
	Value string
	node
}

func NewLabelNode(value string, LineNum int) *LabelNode {
	ret := &LabelNode{Value: value}
	ret.LineNum = LineNum
	return ret
}

func (b *LabelNode) String() string {
	return fmt.Sprintf("*ast2.LabelNode{Value:%s}", b.Value)
}

func (l *LabelNode) C(buf *strings.Builder) {
	buf.Grow(len(l.Value) + 1)
	buf.WriteString(l.Value)
	buf.WriteString(":")
}

// break语句
type BreakStmt struct{}

func NewBreakStmt() BreakStmt {
	return BreakStmt{}
}

func (b BreakStmt) String() string {
	var buf strings.Builder
	buf.WriteString("ast2.BreakStmt{}")
	return buf.String()
}

func (b BreakStmt) C(buf *strings.Builder) {
	buf.Grow(7)
	buf.WriteString("break ;")
}

// continue语句
type ContinueStmt struct{}

func NewContinueStmt() ContinueStmt {
	return ContinueStmt{}
}

func (c ContinueStmt) String() string {
	var buf strings.Builder
	buf.WriteString("ast2.ContinueStmt{}")
	return buf.String()
}

func (c ContinueStmt) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("continue ;")
}

// 常量声明节点
type ConstNode struct {
	TYPE  astdata.Typ
	Value Expr
	Name  string
	node
}

// newConstNode 创建常量声明节点
func newConstNode(name string, LineNum int) *ConstNode {
	c := &ConstNode{Name: name}
	c.LineNum = LineNum
	return c
}

func (n *ConstNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, n) {
		return buf.String()
	}
	buf.WriteString("*ast2.Const{")
	buf.WriteString(fmt.Sprintf("%+v}", *n))
	return buf.String()
}

func (c *ConstNode) C(buf *strings.Builder) {
	var typename string
	if o, ok := c.TYPE.(*Object); ok {
		typename = typeToC(o.Name)
	} else {
		typename = c.TYPE.Typ()
	}
	buf.Grow(60)
	buf.WriteString(enum.Const)
	buf.WriteString(" ")
	buf.WriteString(typename)
	buf.WriteString(" ")
	buf.WriteString(c.Name)
	if c.Value == nil { //没有初始化
		buf.WriteString(" ;")
		return
	}
	buf.WriteString(" = ")
	c.Value.C(buf)
	buf.WriteString(" ;")
}

func (c *ConstNode) CDecl(buf *strings.Builder) {
	buf.WriteString("extern ")
	var typename string
	if o, ok := c.TYPE.(*Object); ok {
		typename = typeToC(o.Name)
	} else {
		typename = c.TYPE.Typ()
	}
	buf.Grow(60)
	buf.WriteString(enum.Const)
	buf.WriteString(" ")
	buf.WriteString(typename)
	buf.WriteString(" ")
	buf.WriteString(c.Name)
	buf.WriteString(" ;")
}

// StructDecl 结构体声明
//
// 缩写：struct declaration 缩写成：StructDecl
type StructDecl struct {
	sbt        *Sbt
	Name       string
	FileName   string
	FieldTable []Field
	TypeParame []astdata.NameAndType
	InFunc     bool
	node
}

func (s *StructDecl) String() string {
	var buf strings.Builder
	if handleNil(&buf, s) {
		return buf.String()
	}
	buf.WriteString("*ast2.StructDecl{")
	buf.WriteString(fmt.Sprintf("%+v}", *s))
	return buf.String()
}

func (s *StructDecl) C(buf *strings.Builder) {
	if !s.InFunc { //全局结构体的C代码由CDecl生产
		return
	}
	s.c(buf)
}

func (s *StructDecl) c(buf *strings.Builder) {
	if s.TypeParame != nil { //跳过未实例化泛型
		return
	}
	buf.Grow(20 + len(s.FieldTable)*15)
	buf.WriteString("typedef struct ")
	buf.WriteString(s.Name)
	buf.WriteString("{\n")
	for _, v := range s.FieldTable {
		buf.WriteString(typeToC(v.Type.Typ()))
		buf.WriteString(" ")
		buf.WriteString(v.Name)
		buf.WriteString(";\n")
	}
	buf.WriteString("}")
	buf.WriteString(s.Name)
	buf.WriteString(";")
}

func (s *StructDecl) CDecl(buf *strings.Builder) {
	s.c(buf)
}

func (s *StructDecl) Typ() string {
	return s.Name
}

func (s *StructDecl) Copy() astdata.Typ { panic("未实现") }
func (s *StructDecl) SetLea(i int)      { panic("未实现") }
func (s *StructDecl) SetTyp()           { panic("未实现") }

func (s *StructDecl) genName() string {
	list := typInfoToStr(s.FieldTable)
	return utils.GenerateGenericTypes(s.Name, list)
}

// FindField 寻找结构体字段中是否有Name
// 返回值Field.Name==""表示结构体字段中没有要查询到
func (info *StructDecl) FindField(Name string) Field {
	for _, v := range info.FieldTable {
		if v.Name == Name {
			return v
		}
	}
	return Field{}
}

func (info *StructDecl) My() string {
	return info.Name
}

func (info *StructDecl) DepLen() int {
	return len(info.FieldTable)
}

func (info *StructDecl) Dep(i int) data.IsItARecursiveType {
	iface := fieldInfo{typ: info.FieldTable[i].Type}
	iface.dep = findTypeDep(info.sbt, info.FieldTable[i].Type)
	return iface
}

// fieldInfo 字段信息
type fieldInfo struct {
	typ astdata.Typ
	dep data.IsItARecursiveType
}

func (info fieldInfo) My() string {
	return info.typ.Typ()
}

func (info fieldInfo) DepLen() int {
	return 1
}

func (info fieldInfo) Dep(i int) data.IsItARecursiveType {
	if i != 0 {
		panic(errutil.NewErr2(errutil.CompileErr, "访问越界"))
	}
	return info.dep
}

func (info fieldInfo) String() string {
	return fmt.Sprintf("typ:%s\tdep:%+v", info.typ, info.dep)
}

// findTypeDep 寻找类型的依赖
func findTypeDep(sbt *Sbt, typ astdata.Typ) data.IsItARecursiveType {
	var info astdata.Typ
	if o, ok := typ.(*Object); ok {
		info, _ = sbt.HaveType(o.Name)
	} else {
		o := typ.(*Objects)
		info, _ = sbt.HaveType(utils.GeneratePackageSymbol(o.Slice[0].Name, o.Slice[1].Name))
	}
	v, _ := info.(*StructDecl)
	return v
}

func typInfoToStr(typ []astdata.NameAndType) []string {
	copys := make([]string, len(typ))
	for i := 0; i < len(typ); i++ {
		copys[i] = typ[i].Type.Typ()
	}
	return copys
}

func typeToC(typ string) string {
	switch typ {
	case enum.String:
		return "char*"
	case enum.Int:
		return "int64_t"
	case enum.UnsafePointer:
		return "void*"
	}
	switch typ[0] {
	case '&':
		return typeToC(typ[1:]) + "*"
	}
	return typ
}

type Field = astdata.NameAndType

type Objects struct {
	T              string
	Slice          []Object
	IsImportSymbol bool //是否是导入符号,由语义检查填充
}

func NewObjects(slice []Object) *Objects {
	return &Objects{Slice: slice}
}

func (o *Objects) String() string {
	var buf strings.Builder
	if handleNil(&buf, o) {
		return buf.String()
	}
	buf.WriteString("*ast2.Objects{")
	for _, v := range o.Slice {
		buf.WriteString(v.String())
	}
	buf.WriteString("}")
	return buf.String()
}

func (o *Objects) FuncName() string {
	var buf strings.Builder
	buf.Grow(50)
	for _, v := range o.Slice[:len(o.Slice)-1] {
		buf.WriteString(v.Name)
		buf.WriteString(".")
	}
	buf.WriteString(o.Slice[len(o.Slice)-1].Name)
	return buf.String()
}

func (o *Objects) Typ() string {
	var buf strings.Builder
	buf.Grow(50)
	if o.Slice[0].Kind&LeaObj != 0 {
		buf.WriteString("&")
	}
	buf.WriteString(o.Slice[0].Name)
	buf.WriteString(enum.PackageSep)
	buf.WriteString(o.Slice[1].Name)
	return buf.String()
}

func (o *Objects) SetTyp() { o.Slice[0].Kind |= TypeObj }

func (o *Objects) Copy() astdata.Typ {
	ret := *o
	return &ret
}

func (o *Objects) SetLea(i int) {
	o.Slice[0].SetLea(i)
}

func (o *Objects) C(buf *strings.Builder) {
	if o.IsImportSymbol {
		//TODO:删除这个特殊处理
		buf.WriteString(o.Slice[1].Name)
		return
	}
	buf.Grow(50)
	slen := len(o.Slice)
	for i := 0; i < slen; i++ {
		o.Slice[i].C(buf)
		if i+1 < slen {
			if o.Slice[i].Kind&StructPtr != 0 && o.Slice[i].Kind&DerefObj == 0 {
				buf.WriteString("->")
			} else {
				if o.IsImportSymbol || o.Slice[i].Kind&EnumObj != 0 {
					buf.WriteString(enum.PackageSep)
				} else {
					buf.WriteString(".")
				}
			}
		}
	}
}

func (o *Objects) CType(buf *strings.Builder) {
	buf.Grow(20)
	buf.WriteString(o.Slice[0].Name)
	buf.WriteString(enum.PackageSep)
	buf.WriteString(o.Slice[1].Name)
}

func (o *Objects) expr() {}

// 自操作语句
// 缩写： Self-operating statement 缩写成 SelfOpStmt
// 源操作数只可能是下列类型
//   - 对象节点 [ast2.Object]
//   - 选择器节点 [ast2.Objects]
type SelfOpStmt struct {
	Dest Expr
	OP   enum.OPSymbol
	node
	nosemicolon bool
}

func newSelfOpStmt(OP enum.OPSymbol, Dest Expr, LineNum int) *SelfOpStmt {
	s := &SelfOpStmt{OP: OP, Dest: Dest}
	s.LineNum = LineNum
	return s
}

func (o *SelfOpStmt) String() string {
	var buf strings.Builder
	if handleNil(&buf, o) {
		return buf.String()
	}
	buf.WriteString("*ast2.SelfOpStmt{")
	buf.WriteString(fmt.Sprintf("%+v}", *o))
	return buf.String()
}

func (o *SelfOpStmt) C(buf *strings.Builder) {
	buf.Grow(10)
	o.Dest.C(buf)
	buf.WriteString(opToStrMap[o.OP])
	if !o.nosemicolon {
		buf.WriteString(";")
	}
}

func (o *SelfOpStmt) SetNosemicolon(nosemicolon bool) {
	o.nosemicolon = nosemicolon
}

// switch节点
type SwitchNode struct {
	codeBlock
	Expr Expr
}

func NewSwitchNode(LineNum int) *SwitchNode {
	ret := &SwitchNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (s *SwitchNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, s) {
		return buf.String()
	}
	buf.WriteString("*ast2.SwitchNode{")
	buf.WriteString(fmt.Sprintf("%+v}", *s))
	return buf.String()
}

func (s *SwitchNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("switch (")
	s.Expr.C(buf)
	buf.WriteString("){")
}

// case节点
type CaseNode struct {
	Expr Expr
	codeBlock
}

func NewCaseNode(LineNum int) *CaseNode {
	ret := &CaseNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (c *CaseNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, c) {
		return buf.String()
	}
	buf.WriteString("*ast2.CasehNode{")
	buf.WriteString(fmt.Sprintf("%+v}", *c))
	return buf.String()
}

func (c *CaseNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("case ")
	c.Expr.C(buf)
	buf.WriteString(":")
}

// default节点
type DefaultNode struct {
	codeBlock
}

func NewDefaultNode(LineNum int) *DefaultNode {
	ret := &DefaultNode{}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (d *DefaultNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, d) {
		return buf.String()
	}
	buf.WriteString("*ast2.DefaultNode{")
	buf.WriteString(fmt.Sprintf("%+v}", *d))
	return buf.String()
}

func (c *DefaultNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("default :")
}

// MethodNode 方法节点
type MethodNode struct {
	*FuncInfo
}

// NewMethodNode 创建函数节点
func NewMethodNode(info *FuncInfo) *MethodNode {
	ret := &MethodNode{FuncInfo: info}
	return ret
}

func (m *MethodNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, m) {
		return buf.String()
	}
	buf.WriteString("&ast.MethodNode{\n")
	buf.WriteString(fmt.Sprintf("type=%s\t", m.FuncInfo.Parame[0].Type.Typ()))
	buf.WriteString(fmt.Sprintf("funcinfo=%s\t", m.FuncInfo.String()))
	buf.WriteString(m.Sbt.String())
	buf.WriteString("}")
	return buf.String()
}

func (m *MethodNode) C(buf *strings.Builder) {
	//Note:依赖CDecl在之前被调用
	f := FuncNode{FuncInfo: m.FuncInfo}
	f.C(buf)
}

func (m *MethodNode) CDecl(buf *strings.Builder) {
	m.Name = astdata.Generate_method_symbol(m.FuncInfo.Parame[0].Type.Typ(), m.FuncInfo.Name)
	f := FuncNode{FuncInfo: m.FuncInfo}
	f.CDecl(buf)
}

// 自动释放块节点
type AutoFreeNode struct {
	codeBlock
	Expr     Expr
	FileName string
}

func NewAutoFreeNode(FileName string, LineNum int) *AutoFreeNode {
	ret := &AutoFreeNode{FileName: FileName}
	ret.codeBlock = newCodeBlock(LineNum)
	return ret
}

func (a *AutoFreeNode) String() string {
	var buf strings.Builder
	if handleNil(&buf, a) {
		return buf.String()
	}
	buf.WriteString("*ast2.AutoFreeNode{")
	buf.WriteString(fmt.Sprintf("%+v}", *a))
	return buf.String()
}

func (a *AutoFreeNode) C(buf *strings.Builder) {
	tmp := VarNode{Name: utils.Generate_mempool_Name(a.LineNum, a.FileName), TYPE: mempool, CType: enum.MemPool, Value: NewCallExpr(mempoolNew, 0, a.Expr), InFunc: true}
	tmp.C(buf)
}

var mempool = NewObject(SymbolObj, enum.MemPool)

var mempoolNew = NewObject(SymbolObj, "mempool__New")

// EnumDecl 枚举声明
type EnumDecl struct {
	Name   string
	Enums  []string
	InFunc bool
	node
}

func NewEnumDecl(Name string, LineNum int, InFunc bool) *EnumDecl {
	ret := &EnumDecl{Name: Name, InFunc: InFunc}
	ret.LineNum = LineNum
	return ret
}

func (s *EnumDecl) String() string {
	var buf strings.Builder
	if handleNil(&buf, s) {
		return buf.String()
	}
	buf.WriteString("*ast2.EnumDecl{")
	buf.WriteString(fmt.Sprintf("%+v}", *s))
	return buf.String()
}

func (s *EnumDecl) C(buf *strings.Builder) {
	if !s.InFunc { //全局结构体的C代码由CDecl生产
		return
	}
	s.c(buf)
}

func (s *EnumDecl) c(buf *strings.Builder) {
	elen := len(s.Enums)
	buf.Grow(20 + elen*10)
	buf.WriteString("typedef enum {")
	for i := 0; i < elen; i++ {
		buf.WriteString(s.Enums[i])
		if i+1 < elen {
			buf.WriteString(",")
		}
	}
	buf.WriteString("} ")
	buf.WriteString(s.Name)
	buf.WriteString(";")
}

func (s *EnumDecl) CDecl(buf *strings.Builder) {
	s.c(buf)
}

func (s *EnumDecl) Typ() string {
	return s.Name
}

func (s *EnumDecl) Copy() astdata.Typ { panic("未实现") }
func (s *EnumDecl) SetLea(i int)      { panic("未实现") }
func (s *EnumDecl) SetTyp()           { panic("未实现") }

// Array 数组类型
type Array struct {
	Len  Expr
	TYPE astdata.Typ
	//下列字段用于获取类型名
	once    sync.Once
	UStr    string
	sbt     *Sbt
	t       *Tree
	LineNum int
}

func (c *Array) String() string {
	var buf strings.Builder
	if handleNil(&buf, c) {
		return buf.String()
	}
	buf.WriteString("*ast2.Array{")
	buf.WriteString(fmt.Sprintf("%+v}", *c))
	return buf.String()
}

func (c *Array) SetTyp() {}

func (c *Array) Copy() astdata.Typ {
	ret := *c
	return &ret
}

func (c *Array) SetLea(i int) {
	c.TYPE.SetLea(i)
}

func (a *Array) Typ() string {
	a.once.Do(func() {
		lenstr, ok := sum(a.Len, a.sbt)
		if !ok {
			a.t.errctx.Panic(a.t.Filename, a.LineNum, nil, errcode.ArrayLenNotCompileTimeConstExpr)
		}
		var buf strings.Builder
		buf.WriteString("[")
		buf.WriteString(lenstr)
		buf.WriteString("]")
		buf.WriteString(a.TYPE.Typ())
		a.UStr = buf.String()
	})
	return a.UStr
}

// IndexExpr  索引表达式
// 缩写index expression 缩写成 IndexExpr
type IndexExpr struct {
	X     Expr
	Index Expr
	node
}

func NewIndexExpr(X Expr, LineNum int) *IndexExpr {
	ret := &IndexExpr{X: X}
	ret.LineNum = LineNum
	return ret
}

func (l *IndexExpr) String() string {
	var buf strings.Builder
	if handleNil(&buf, l) {
		return buf.String()
	}
	buf.WriteString("*ast2.IndexExpr{")
	buf.WriteString(fmt.Sprintf("%+v}", *l))
	return buf.String()
}

func (l *IndexExpr) C(buf *strings.Builder) {
	buf.Grow(5)
	l.X.C(buf)
	buf.WriteString("[")
	l.Index.C(buf)
	buf.WriteString("]")
}

func (l *IndexExpr) expr() {}

// GenericInstantiation 泛型实例化
type GenericInstantiation struct {
	BaseName   astdata.Typ
	ActualType []astdata.Typ
	FileName   string
	node
}

func (g *GenericInstantiation) String() string {
	var buf strings.Builder
	if handleNil(&buf, g) {
		return buf.String()
	}
	buf.WriteString("&ast.GenericInstantiation{BaseName:")
	buf.WriteString(g.BaseName.Typ())
	fmt.Fprintf(&buf, "\tLineNum:%d\tActualType:", g.LineNum)
	for _, v := range g.ActualType {
		buf.WriteString(v.Typ())
		buf.WriteString(" ")
	}
	buf.WriteString("}")
	return buf.String()
}

func (g *GenericInstantiation) SetTyp() {}

func (g *GenericInstantiation) Typ() string {
	list, havenil := typToStr(g.ActualType)
	if havenil {
		return ""
	}
	return utils.GenerateGenericTypes(g.BaseName.Typ(), list)
}

func (g *GenericInstantiation) C(buf *strings.Builder) {
	panic("不应执行的路径")
}

func typToStr(typ []astdata.Typ) ([]string, bool) {
	list := make([]string, len(typ))
	for i, v := range typ {
		if v == nil {
			return nil, true
		}
		list[i] = v.Typ()
	}
	return list, false
}

func (g *GenericInstantiation) Copy() astdata.Typ {
	ret := *g
	ret.BaseName = g.BaseName.Copy()
	ret.ActualType = copyTyp(ret.ActualType)
	return &ret
}

func copyTyp(typ []astdata.Typ) []astdata.Typ {
	copys := make([]astdata.Typ, len(typ))
	for i, v := range typ {
		copys[i] = v.Copy()
	}
	return copys
}

func copyNameAndTyp(s []astdata.NameAndType) []astdata.NameAndType {
	copys := make([]astdata.NameAndType, len(s))
	for i, v := range s {
		copys[i].Name = v.Name
		copys[i].Type = v.Type.Copy()
	}
	return copys
}

func (g *GenericInstantiation) SetLea(i int) {
	g.BaseName.SetLea(i)
}

func (g *GenericInstantiation) FuncName() string {
	return g.Typ()
}

func (g *GenericInstantiation) expr() {}

// DerefExpr 解引用节点
type DerefExpr struct {
	Value Expr
	node
}

func (d *DerefExpr) String() string {
	var buf strings.Builder
	if handleNil(&buf, d) {
		return buf.String()
	}
	buf.WriteString("*ast2.Dereference")
	buf.WriteString(fmt.Sprintf("%+v}", *d))
	return buf.String()
}

func (d *DerefExpr) expr() {}

func (d *DerefExpr) C(buf *strings.Builder) {
	buf.Grow(5)
	buf.WriteString("*(")
	d.Value.C(buf)
	buf.WriteString(")")
}

func handleNil[T any](buf *strings.Builder, n *T) bool {
	if n == nil {
		buf.WriteString(fmt.Sprintf("%T{<nil>}", n))
		return true
	}
	return false
}
